package com.base.component.ai.workflow.handle;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.base.component.ai.agent.bo.ContextBO;
import com.base.component.ai.agent.bo.ContextParamBO;
import com.base.component.ai.workflow.core.NodeFunctionParent;
import com.base.component.ai.workflow.core.NodeHandle;
import com.base.component.ai.workflow.flow.Flow;
import com.base.component.ai.workflow.logs.NodeLog;
import com.base.component.ai.workflow.logs.NodeLogFunction;
import com.base.component.ai.workflow.node.Node;
import com.base.component.ai.workflow.node.NodeFunction;
import com.gitee.magic.core.exception.ApplicationException;

@Component
public class NodeHandleFunction<MSG,AP extends ContextParamBO,PP> implements NodeHandle<MSG,AP,PP>{
	
	@Autowired(required = false)
	private NodeFunctionParent nodeFunctionParent;
	
	@Override
	public <T extends Node> boolean support(Class<T> cls) {
		return cls.equals( NodeFunction.class);
	}

	@Override
	public <T extends Node>List<Flow> execute(ContextBO<MSG,AP,PP> context,Map<String,Object> params,Flow flow,T node,Consumer<NodeLog> c) {
		NodeFunction d=(NodeFunction)node;
		NodeLogFunction<MSG, AP, PP> nodeLog=new NodeLogFunction<>();
		nodeLog.setContext(context);
		try {
			Method method=nodeFunctionParent.getClass().getMethod(d.getMethodName(),ContextBO.class);
			Object v=method.invoke(nodeFunctionParent, context);
			nodeLog.setValue(v);
			params.put(d.getVariableName(), v);
		} catch (NoSuchMethodException e) {
			throw new ApplicationException(e);
		} catch (SecurityException e) {
			throw new ApplicationException(e);
		} catch (IllegalAccessException e) {
			throw new ApplicationException(e);
		} catch (IllegalArgumentException e) {
			throw new ApplicationException(e);
		} catch (InvocationTargetException e) {
			throw new ApplicationException(e);
		}
		c.accept(nodeLog);
		return flow.getNexts();
	}
	
}
